package com.godenwater.recv.service;

import com.godenwater.core.spring.Application;
import com.godenwater.core.spring.BaseDao;
import com.godenwater.recv.model.CommonMessage;
import com.godenwater.recv.server.yln.YlnMessageHeader;
import com.godenwater.yanyu.utils.ByteUtil;
import com.godenwater.web.manager.StationDataManager;
import com.godenwater.web.manager.StationManager;
import com.godenwater.web.rtu.model.RtuStationData;
import com.godenwater.web.rtu.model.RtuStationModel;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 1.1【亿立能】报文消费者
 *
 * @author lipujun
 * @ClassName: MessageConsumer
 * @Description: 通过线程的方式将“报文”解析，然后入库，这是消息进行处理的第一个环节
 * <p>
 * 注意：只启动一个消费者
 * @date Mar 14, 2013
 */
public class MessageYlnConsumer extends AbstractMessageConsumer implements
        Runnable {

    private static Logger logger = LoggerFactory
            .getLogger(MessageYlnConsumer.class);

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static long DAY = 24 * 60 * 60 * 1000;

    private static long HOUR = 60 * 60 * 1000;

    private static String KEY = "messages";

    private BaseDao dao = (BaseDao) Application.getInstance()
            .getBean("baseDao");

    public MessageYlnConsumer() {

    }

    @Override
    public void run() {
        int i = 0;

    }

    /**
     * 处理业务逻辑
     * <p>
     * 第一步：原始报文入库
     * <p>
     * 第二步：判断单报、多报。单报写“入库队列”；多报写文件，并根据最后一条报文写“合并队列”
     *
     * @param message
     */
    public void process(String channel, CommonMessage message) throws Exception {

        // logger.info("原始报文开始入库！");
        boolean crcFlag = true;
        YlnMessageHeader header = (YlnMessageHeader) message.getHeader();
        byte[] funcCode = header.getSTART_BIT();
        //logger.info(">YLN DATA " + new String(funcCode) + new String(message.getContent()));

        // 解析报文体
        String funccode = new String(funcCode);
        String content = new String(message.getContent(), "GB2312");

        //实时数据
        //AAA;61079250;61079250;yilinengshuiwen;qipaoceshi;2017-03-10 15:00:00;1.61,12.2,0,0;水位(m),供电电压(V),环境温度(℃),水势;$END
        if (StringUtils.equalsIgnoreCase(funccode, "AAA")) {
            processRealData(content);
        }

        //密集数据
        if (StringUtils.equalsIgnoreCase(funccode, "BAA")) {
            processMijiData(message.getContent());
        }


    }

    /**
     * 根据实际的内容，将数据拆分并写入到数据库中
     *
     * @param content
     */
    public void processRealData(String content) {

        try {
            String[] msg = content.split(";");
            String stcd = msg[1];
            String viewtime = msg[5];
            String viewdata = msg[6];
            String viewnote = msg[7];
            // logger.info(">YLN REAL DATA stcd " + stcd + " viewtime " + viewtime + " viewdata " + viewdata + " viewnote " + viewnote);

            String[] data = msg[6].split(",");
            String[] note = viewnote.split(",");
            //   String stcd8 = convertStcd(stcd); //需要进行站码转换
            RtuStationModel station = StationManager.getInstance().getStation(stcd);
            if (station != null) {
                String stcd8 = station.getStcd8();
                int dlen = data.length;
                int nlen = note.length;

                if (dlen == nlen) {
                    //水位(m),供电电压(V),环境温度(℃),水势
                    Date vd = sdf.parse(viewtime);
                    for (int i = 0; i < nlen; i++) {
                        if (note[i].indexOf("雨量") != -1) {
                            RtuStationData oldData = StationDataManager.getInstance().getStation(stcd8);
                            if (oldData == null) {
                                RtuStationData newData = new RtuStationData();
                                newData.setStcd(stcd8);
                                newData.setRain5(data[i]);
                                newData.setRain60(data[i]);
                                StationDataManager.getInstance().update(newData);
                            } else {
                                //判断时间，根据时间的纬度来区分5分钟和小时
                                String[] tm = viewtime.split(":");
                                if (tm[1].equals("00")) {
                                    String orain5 = oldData.getRain5();//取上次5分钟的数据
                                    String orain = oldData.getRain60();
                                    BigDecimal b5 = new BigDecimal(orain5);
                                    BigDecimal b1 = new BigDecimal(data[i]);
                                    BigDecimal b2 = new BigDecimal(orain);
                                    oldData.setRain60(data[i]);
                                    oldData.setRain5(data[i]);//设置新5分钟的数据
                                    StationDataManager.getInstance().update(oldData);
                                    logger.info(">YLN REAL RAIN DATA stcd " + stcd + "<" + stcd8 + "> viewtime " + viewtime + " value " + b1.subtract(b2).doubleValue());
                                    double minus = b1.subtract(b5).doubleValue();
                                    if (minus > 0) {
                                        writeYYConnvertData(stcd8, vd, "1", 23, b1.subtract(b5).doubleValue(), 41);//写入5分钟数据
                                    }
                                    writeYYConnvertData(stcd8, vd, "1", 22, b1.subtract(b2).doubleValue(), 41);//写入整点数据
                                } else {
                                    String orain = oldData.getRain5();
                                    BigDecimal b1 = new BigDecimal(data[i]);
                                    BigDecimal b2 = new BigDecimal(orain);
                                    oldData.setRain5(data[i]);
                                    StationDataManager.getInstance().update(oldData);
                                    logger.info(">YLN REAL RAIN DATA stcd " + stcd + "<" + stcd8 + "> viewtime " + viewtime + " value " + b1.subtract(b2).doubleValue());

                                    double minus = b1.subtract(b2).doubleValue();
                                    if (minus > 0) {
                                        writeYYConnvertData(stcd8, vd, "1", 23, minus, 41);//写入5分钟数据
                                    }
                                }

                            }
                        }

                        if (note[i].indexOf("水位") != -1) {
                            BigDecimal dtmel = station.getDtmel();
                            if (dtmel != null) {
                                BigDecimal value = new BigDecimal(data[i]);
                                logger.debug(">YLN REAL RAIN DATA stcd " + stcd + "<" + stcd8 + "> viewtime " + viewtime + " value " + Double.parseDouble(data[i]) + " dtmel " + dtmel.doubleValue());
                                writeYYConnvertData(stcd8, vd, "1", 11, dtmel.add(value).doubleValue(), 41);
                            } else {
                                logger.debug(">YLN REAL RAIN DATA stcd " + stcd + "<" + stcd8 + "> viewtime " + viewtime + " value " + Double.parseDouble(data[i]));
                                writeYYConnvertData(stcd8, vd, "1", 11, Double.parseDouble(data[i]), 41);
                            }

                        }
                        if (note[i].indexOf("电压") != -1) {
                            writeYYConnvertData(stcd8, vd, "1", 51, Double.parseDouble(data[i]), 41);
                        }

                    }
                }
            }
            //原始报文入库
            String id = UUID.randomUUID().toString();
            String msgstr = "$AAA" + content;
            this.writeRtuMessage(id, stcd, "YLN", "", "AAA", 1, sdf.parse(viewtime), 1, 1, msgstr, true, "", "", 0, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //处理密集型报文数据
    //4 + 4 + 4 + 16 + 2 + 1 + 1 + { 2 + 1 + 1 + 1 + 1 + 4×n }×m + 4
    //$BAA(4) 站号(4) 口令(4) 参数说明（16） 数据包总长（2） 时间间隔（1） 参数（1）
    //数据类型 { 2 + 1 + 1 + 1 + 1 + 4×n }
    //{ 年 月 日 时 分(参数1 参数2……参数n) }1
    //{ 年 月 日 时 分(参数1 参数2……参数n) }2
    //		………………………………………………
    //{ 年 月 日 时 分(参数1 参数2……参数n) }m
    //		$END
    public void processMijiData(byte[] buffer) {
        int pos = 0;

        try {
            // 测站
            byte[] stcd = new byte[4];
            System.arraycopy(buffer, pos, stcd, 0, 4);
            pos = pos + 4;
            //ByteUtil.bytesToInt(stcd);
            String xStcd = "" + ByteUtil.bytesToInt(new byte[]{stcd[3], stcd[2], stcd[1], stcd[0]});
            String mStcd = convertStcd(xStcd); //需要进行站码转换
            //System.out.println(">> stcd " + mStcd);
            // 口令
            byte[] pwd = new byte[4];
            System.arraycopy(buffer, pos, pwd, 0, 4);
            pos = pos + 4;

            // 说明
            byte[] note = new byte[16];
            System.arraycopy(buffer, pos, note, 0, 16);
            pos = pos + 16;
            //System.out.println(">> note " + new String(note));

            //数据包总长（2） 时间间隔（1） 参数（1）
            byte[] blen = new byte[2];
            System.arraycopy(buffer, pos, blen, 0, 2);
            pos = pos + 2;
            //System.out.println(">> 数据包总长 " + ByteUtil.bytesToShort(new byte[]{blen[1], blen[0]}));

            //时间间隔（1）
            byte[] sep = new byte[1];
            System.arraycopy(buffer, pos, sep, 0, 1);
            pos = pos + 1;
            //System.out.println(">> 时间间隔 " + ByteUtil.bytesToUbyte(sep));

            //参数（1）
            byte[] datatype = new byte[1];
            System.arraycopy(buffer, pos, datatype, 0, 1);
            pos = pos + 1;
            //ByteUtil.bytesToUbyte(param);
            //System.out.println(">> 参数数据类型 " + ByteUtil.bytesToUbyte(datatype));

            //获取时间
            byte[] year = new byte[2];
            System.arraycopy(buffer, pos, year, 0, 2);
            pos = pos + 2;
            ByteUtil.bytesToShort(year);
            byte[] month = new byte[1];
            System.arraycopy(buffer, pos, month, 0, 1);
            pos = pos + 1;
            //ByteUtil.bytesToUbyte(sep);
            byte[] day = new byte[1];
            System.arraycopy(buffer, pos, day, 0, 1);
            pos = pos + 1;
            byte[] hour = new byte[1];
            System.arraycopy(buffer, pos, hour, 0, 1);
            pos = pos + 1;
            //ByteUtil.bytesToUbyte(sep);
            byte[] minute = new byte[1];
            System.arraycopy(buffer, pos, minute, 0, 1);
            pos = pos + 1;
//ByteUtil.bytesToUbyte(sep);

            int nMonth = ByteUtil.bytesToUbyte(month);
            int nDay = ByteUtil.bytesToUbyte(day);
            int nHour = ByteUtil.bytesToUbyte(hour);
            int nMinute = ByteUtil.bytesToUbyte(minute);

            Date viewtime = sdf.parse(ByteUtil.bytesToShort(new byte[]{year[1], year[0]}) + "-" + (nMonth < 10 ? "0" + nMonth : nMonth) + "-" + (nDay < 10 ? "0" + nDay : nDay) + " " + (nHour < 10 ? "0" + nHour : nHour) + ":" + (nMinute < 10 ? "0" + nMinute : nMinute) + ":00");
            DateTime dt = new DateTime(viewtime);
//System.out.println(">> 时间 " + ByteUtil.bytesToShort(new byte[]{year[1], year[0]}) + ByteUtil.bytesToUbyte(month) + ByteUtil.bytesToUbyte(day) + ByteUtil.bytesToUbyte(hour) + ByteUtil.bytesToUbyte(minute));
            logger.debug(">YLN MIJI DATA stcd" + new String(stcd) + "<" + mStcd + ">  时间 " + sdf.format(viewtime) + " 时间间隔 " + ByteUtil.bytesToUbyte(sep) + "datatype " + ByteUtil.bytesToUbyte(datatype));

            //原始报文入库
            String id = UUID.randomUUID().toString();
            String msgstr = ByteUtil.toHexString("$BAA".getBytes()) + ByteUtil.toHexString(buffer);
            this.writeRtuMessage(id, new String(stcd), "YLN", "",
                    "BAA", 1, viewtime, 1, 1, msgstr,
                    true, "", "", 0, 0);


            dt = dt.minusHours(1).minusMinutes(dt.getMinuteOfHour());//将此数据标志为从前一小时开始的时间节点

            //长度/sep
            int dlen = 12;

            if (new String(note).indexOf("雨量") != -1) {
                for (int i = 0; i < dlen; i++) {
                    dt = dt.plusMinutes(5);

                    byte[] data = new byte[4];
                    System.arraycopy(buffer, pos, data, 0, 4);
                    pos = pos + 4;

                    String rainValue = "0.0";
                    if (datatype[0] == (byte) 0x1E) {//采用整形数据，加两位小数位，有正负之说
                        BigInteger bi = new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16);
                        //rainValue = bi.floatValue();
                        DecimalFormat decimalFormat = new DecimalFormat(".00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
                        rainValue = decimalFormat.format(bi.intValue() / 100);//format 返回的是字符串
                        logger.debug(">> 0x1E rain data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + bi.intValue() + " = " + rainValue);
                    }

                    if (datatype[0] == (byte) 0x00) {//采用浮点型数据类型，直接获取得到小数位
                        Float value = Float.intBitsToFloat(new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16).intValue());
                        //rainValue = value;
                        DecimalFormat decimalFormat = new DecimalFormat(".00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
                        rainValue = decimalFormat.format(value);
                        logger.debug(">> 0x00 rain data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + value);
                    }

                    //下一步工作，就数据入库。

                    //-----
                    if (new String(note).indexOf("雨量") != -1) {
                        RtuStationData oldData = StationDataManager.getInstance().getStation(mStcd);
                        if (oldData == null) {
                            RtuStationData newData = new RtuStationData();
                            newData.setStcd(mStcd);
                            newData.setRain5("" + rainValue);
                            newData.setRain60("" + rainValue);
                            StationDataManager.getInstance().update(newData);
                        } else {
                            String orain = oldData.getRain5();
                            BigDecimal b1 = new BigDecimal(rainValue);
                            BigDecimal b2 = new BigDecimal(orain);


                            oldData.setRain5(rainValue);
                            StationDataManager.getInstance().update(oldData);
                            logger.debug(">YLN MIJI RAIN DATA stcd " + stcd + "<" + mStcd + "> viewtime " + viewtime + " value " + b1.subtract(b2).doubleValue());
                            writeYYConnvertData(mStcd, dt.toDate(), "1", 23, b1.subtract(b2).doubleValue(), 41);
                        }
                    }
                }
            }

            if (new String(note).indexOf("水位") != -1) {
                for (int i = 0; i < dlen; i++) {
                    dt = dt.plusMinutes(5);

                    byte[] data = new byte[4];
                    System.arraycopy(buffer, pos, data, 0, 4);
                    pos = pos + 4;

                    if (datatype[0] == (byte) 0x1E) {//采用整形数据，加两位小数位，有正负之说
                        BigInteger bi = new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16);
                        //writeYYConnvertData(mStcd,  dt.toDate(), "1", 11, bi.intValue(), 41);
                        RtuStationModel station = StationManager.getInstance().getStation(xStcd);
                        if (station != null) {
                            BigDecimal dtmel = station.getDtmel();
                            if (dtmel != null) {
                                BigDecimal value = new BigDecimal(bi.intValue());
                                logger.debug(">> 0x1E river data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + bi.intValue() + " dtmel " + dtmel.doubleValue());
                                writeYYConnvertData(mStcd, dt.toDate(), "1", 11, dtmel.add(value).doubleValue(), 41);
                            } else {
                                logger.debug(">> 0x1E river data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + bi.intValue());
                                writeYYConnvertData(mStcd, dt.toDate(), "1", 11, bi.intValue(), 41);
                            }
                        } else {
                            logger.debug(">> 0x1E river data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + bi.intValue());
                            writeYYConnvertData(mStcd, dt.toDate(), "1", 11, bi.intValue(), 41);
                        }


                    }

                    if (datatype[0] == (byte) 0x00) {//采用浮点型数据类型，直接获取得到小数位
                        Float value = Float.intBitsToFloat(new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16).intValue());
                        System.out.println(">> 0x00 river data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + value);
                        //new BigDecimal(value).doubleValue();
                        //writeYYConnvertData(mStcd, dt.toDate(), "1", 11,new BigDecimal(Float.toString(value)).doubleValue(), 41);
                        RtuStationModel station = StationManager.getInstance().getStation(xStcd);
                        if (station != null) {
                            BigDecimal dtmel = station.getDtmel();
                            if (dtmel != null) {
                                BigDecimal xvalue = new BigDecimal(Float.toString(value));
                                //dtmel.add(value);
                                writeYYConnvertData(mStcd, dt.toDate(), "1", 11, dtmel.add(xvalue).doubleValue(), 41);
                            } else {
                                writeYYConnvertData(mStcd, dt.toDate(), "1", 11, new BigDecimal(Float.toString(value)).doubleValue(), 41);
                            }
                        } else {
                            writeYYConnvertData(mStcd, dt.toDate(), "1", 11, new BigDecimal(Float.toString(value)).doubleValue(), 41);
                        }
                    }
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 亿立能的协议中，有一个测站的转换关系，针对荆州的测站编码对应关系，因站数太少，写在程序中
     *
     * @return
     */
    public String convertStcd(String key) {
        RtuStationModel station = StationManager.getInstance().getStation(key);

        if (station != null) {
            return station.getStcd8();
        } else {
            //荆州测站
            Hashtable<String, String> table = new Hashtable();

            table.put("16121501", "61058900");
            table.put("16121503", "61056150");
            table.put("16121504", "61057000");
            table.put("17030601", "61015020");
            table.put("17031701", "61520200");
            table.put("17031702", "61521250");
            table.put("17032101", "61015802");
            table.put("16011901", "62213240");
            table.put("60975250", "60975250");
            table.put("61077500", "61077500");
            table.put("62165000", "62165000");
            table.put("61079250", "61079250");
            table.put("61074750", "61074750");
            table.put("61500700", "61500700");
            table.put("61007625", "61007625");


            if (table.get(key) != null) {
                return table.get(key);
            } else {
                return "";
            }
        }


    }


    public static void main(String[] arg) {

        byte[] data = new byte[]{0x42, 0x4e, 0x00, 0x00};
        Float value = Float.intBitsToFloat(new BigInteger("424e0000", 16).intValue());
        System.out.println(">>. " + value.doubleValue());

        BigDecimal b1 = new BigDecimal(Double.toString(1.01));
        BigDecimal b2 = new BigDecimal(Double.toString(1.0));
        System.out.println(">. " + b1.subtract(b2).doubleValue());

        byte[] aaa = new byte[2];
        MessageYlnConsumer xxx = new MessageYlnConsumer();

        String message = "7E7E0020320500FFFFFF4A800802000114061408373305ACB0";
        message = message.substring(0, 32);
        System.out.println(">. " + message);
        // //+ message.substring(44);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sendtime = "2014-06-17 11:00:00";
        Date send;
        try {
            send = sdf.parse(sendtime);

            Date now = new Date();

            long diff = now.getTime() - send.getTime();
            if (diff / HOUR > 6) {
                System.out.println(">>>>>" + diff / HOUR);
            }
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}
